package cn.bearspark.happening.provider.rpc;

import cn.bearspark.common.dto.Page;
import cn.bearspark.common.util.ConvertBeanUtil;
import cn.bearspark.common.util.ConvertInfoUtil;
import cn.bearspark.happening.dto.happening.*;
import cn.bearspark.happening.provider.dao.co.HappeningCO;
import cn.bearspark.happening.provider.service.BookLiveService;
import cn.bearspark.happening.provider.service.HappeningService;
import cn.bearspark.happening.provider.service.VoteService;
import cn.bearspark.happening.provider.service.bo.BookLiveBO;
import cn.bearspark.happening.provider.service.bo.HappeningBO;
import cn.bearspark.happening.provider.service.bo.VoteSimpleBO;
import cn.bearspark.happening.rpc.HappeningRpc;
import org.apache.dubbo.config.annotation.DubboService;
import org.springframework.stereotype.Component;
import org.springframework.util.CollectionUtils;

import java.util.*;
import java.util.stream.Collectors;

/**
 * @author f
 */
@Component
@DubboService
public class HappeningRpcImpl implements HappeningRpc {

    private final HappeningService happeningService;
    private final BookLiveService bookLiveService;
    private final VoteService voteService;

    public HappeningRpcImpl(HappeningService happeningService,
                            BookLiveService bookLiveService,
                            VoteService voteService) {
        this.happeningService = happeningService;
        this.bookLiveService = bookLiveService;
        this.voteService = voteService;
    }

    @Override
    public long publish(PublishHappeningReqDTO publishHappeningReqDTO) {
        long happeningId = happeningService.publish(publishHappeningReqDTO);
        long userId = publishHappeningReqDTO.getUserId();

        BookLiveInfo4Publish bookLiveInfo = publishHappeningReqDTO.getBookLiveInfo();
        if (bookLiveInfo != null) {
            bookLiveService.publish(bookLiveInfo, happeningId, userId);
        }

        VoteInfo4Publish voteInfo = publishHappeningReqDTO.getVoteInfo();
        if (voteInfo != null) {
            voteService.publish(voteInfo, happeningId, userId);
        }

        return happeningId;
    }

    @Override
    public Page<HappeningDTO> pageQuerySAF(long userId, List<Long> followerIdList, int pageNum, int pageSize) {
        Page<HappeningBO> happeningBasePage =
                happeningService.pageQuerySAF(userId, followerIdList, pageNum, pageSize);
        Page<HappeningDTO> happeningDTOPage = new Page<>();
        happeningDTOPage.setTotal(happeningBasePage.getTotal());
        happeningDTOPage.setRecords(asmHappeningDTOList(userId, happeningBasePage.getRecords()));
        return happeningDTOPage;
    }

    // 组装分页查询动态的信息
    private List<HappeningDTO> asmHappeningDTOList(long userId, List<HappeningBO> happeningBOList) {
        // 用于查询预约直播的信息的预约直播 id 集合
        List<Long> bookLiveIdList = new ArrayList<>();
        // 用于查询投票信息的投票 id 集合
        List<Long> voteIdList = new ArrayList<>();
        // 查询引用的动态信息的动态 id 集合
        Set<Long> quotedHappeningIdSet = new HashSet<>();

        // 统计需要查询的信息
        happeningBOList.forEach(happeningBO -> {
            Long bookLiveId = happeningBO.getBookLiveId();
            if (bookLiveId != null) {
                bookLiveIdList.add(bookLiveId);
            }
            Long voteId = happeningBO.getVoteId();
            if (voteId != null) {
                voteIdList.add(voteId);
            }
            Long quoteHappeningId = happeningBO.getQuotedHappeningId();
            if (quoteHappeningId != null) {
                quotedHappeningIdSet.add(quoteHappeningId);
            }
        });

        // 查询引用的动态信息
        List<HappeningBO> quotedHappeningBOList = !CollectionUtils.isEmpty(quotedHappeningIdSet) ?
                happeningService.listQuoteHappeningInfo(quotedHappeningIdSet) :
                new ArrayList<>();

        // 补充需要查询的信息
        quotedHappeningBOList.forEach(quotedHappeningBO -> {
            Long bookLiveId = quotedHappeningBO.getBookLiveId();
            if (bookLiveId != null) {
                bookLiveIdList.add(bookLiveId);
            }
            Long voteId = quotedHappeningBO.getVoteId();
            if (voteId != null) {
                voteIdList.add(voteId);
            }
        });

        // 查询预约直播的信息
        Map<Long, BookLiveBO> bookLiveBOMap = !CollectionUtils.isEmpty(bookLiveIdList) ?
                bookLiveService.mapBookLiveInfo(bookLiveIdList, userId) :
                new HashMap<>();

        // 查询投票的信息
        Map<Long, VoteSimpleBO> voteSimpleBOMap = !CollectionUtils.isEmpty(voteIdList) ?
                voteService.mapVoteSimpleInfo(voteIdList) :
                new HashMap<>();

        // 组装引用动态的完整信息
        Map<Long, HappeningDTO> quotedHappeningDTOMap = quotedHappeningBOList.stream().collect(Collectors.toMap(
                HappeningBO::getHappeningId,
                quotedHappeningBO -> asmHappeningDTO(
                        quotedHappeningBO,
                        bookLiveBOMap.get(quotedHappeningBO.getBookLiveId()),
                        voteSimpleBOMap.get(quotedHappeningBO.getVoteId())
                )
        ));

        // 组装动态的完整信息
        return happeningBOList.stream().map(happeningBO -> {
            HappeningDTO happeningDTO = asmHappeningDTO(
                    happeningBO,
                    bookLiveBOMap.get(happeningBO.getBookLiveId()),
                    voteSimpleBOMap.get(happeningBO.getVoteId())
            );
            happeningDTO.setQuotedHappeningDTO(quotedHappeningDTOMap.get(happeningBO.getQuotedHappeningId()));
            return happeningDTO;
        }).toList();
    }

    @Override
    public List<HappeningDTO> pageQueryByUserId(long operatorId, long userId, int pageNum, int pageSize) {
        return asmHappeningDTOList(operatorId,
                happeningService.pageQueryByUserId(operatorId, userId, pageNum, pageSize));
    }

    @Override
    public long forward(ForwardReqDTO forwardReqDTO) {
        return happeningService.forward(forwardReqDTO);
    }

    @Override
    public DetailDTO detail(long userId, long happeningId) {
        List<HappeningBO> happeningBOList = happeningService.detail(userId, happeningId);

        // 如果是空集合，则说明该用户没有权限，直接返回 null
        if (happeningBOList.isEmpty()) {
            return null;
        }

        HappeningBO happeningBO = happeningBOList.get(0);
        DetailDTO detailDTO = ConvertBeanUtil.convert(happeningBO, DetailDTO.class);

        if (happeningBOList.size() == 1) {
            // 如果只有一个动态，则说明这个动态没有引用别的动态，需要查询它的 预约直播 和 投票 的信息
            detailDTO.setBookLiveInfo(ConvertInfoUtil.convert(
                    bookLiveService.getBookLiveInfo(happeningBO.getBookLiveId(), userId), BookLiveInfo4Display.class));
            detailDTO.setVoteSimpleInfo(ConvertInfoUtil.convert(
                    voteService.getVoteSimpleInfo(happeningBO.getVoteId()), VoteSimpleInfo4Display.class));
        } else {
            // 如果有两个动态，则说明这个动态引用了别的动态，需要查询它 引用动态 的信息
            // 它不可能有 预约直播 和 投票 的信息，而它引用的动态可能有
            HappeningBO quotedHappeningBO = happeningBOList.get(1);
            detailDTO.setQuotedHappeningDTO(asmHappeningDTO(
                    quotedHappeningBO,
                    bookLiveService.getBookLiveInfo(quotedHappeningBO.getBookLiveId(), userId),
                    voteService.getVoteSimpleInfo(quotedHappeningBO.getVoteId())
            ));
        }

        return detailDTO;
    }

    // 组装动态的数据传输对象
    private static HappeningDTO asmHappeningDTO(HappeningBO happeningBO,
                                                BookLiveBO bookLiveBO,
                                                VoteSimpleBO voteSimpleBO) {
        HappeningDTO happeningDTO = ConvertBeanUtil.convert(happeningBO, HappeningDTO.class);
        happeningDTO.setBookLiveInfo(ConvertInfoUtil.convert(bookLiveBO, BookLiveInfo4Display.class));
        happeningDTO.setVoteSimpleInfo(ConvertInfoUtil.convert(voteSimpleBO, VoteSimpleInfo4Display.class));
        return happeningDTO;
    }

    @Override
    public void like(long userId, long happeningId, int liked) {
        happeningService.like(userId, happeningId, liked);
    }

    @Override
    public void delete(long userId, long happeningId) {
        HappeningCO happeningCO = happeningService.delete(userId, happeningId);
        if (happeningCO == null) {
            return;
        }

        // 删除 动态中发布的预约直播信息
        Long bookLiveId = happeningCO.getBookLiveId();
        if (bookLiveId != null) {
            bookLiveService.delete(bookLiveId);
        }

        // 删除 动态中发布的投票信息
        Long voteId = happeningCO.getVoteId();
        if (voteId != null) {
            voteService.delete(voteId);
        }
    }

    @Override
    public void modify(ModifyReqDTO modifyReqDTO) {
        happeningService.modify(modifyReqDTO);
    }

    @Override
    public void incrCommentNum(long happeningId) {
        happeningService.incrCommentNum(happeningId);
    }

    @Override
    public void decrCommentNum(long happeningId, long decrement) {
        happeningService.decrCommentNum(happeningId, decrement);
    }

    @Override
    public long getLikeNum(long happeningId) {
        return happeningService.getLikeNum(happeningId);
    }

    @Override
    public long getForwardNum(long happeningId) {
        return happeningService.getForwardNum(happeningId);
    }

    @Override
    public long getCommentNum(long happeningId) {
        return happeningService.getCommentNum(happeningId);
    }

    @Override
    public void onHappeningDeadline(List<String> infoList) {
        happeningService.onHappeningDeadline(infoList);
    }

    @Override
    public boolean isCommentable(long happeningId) {
        return happeningService.isCommentable(happeningId);
    }

    @Override
    public LCFNumInfoDTO getLCFNumInfo(long happeningId) {
        return happeningService.getLCFNumInfo(happeningId);
    }

    @Override
    public Map<Long, LCFNumInfoDTO> mapLCFNumInfo(List<Long> happeningIdList) {
        return happeningService.mapLCNumInfo(happeningIdList);
    }
}
